// *********************************************************
//      Copyright (c) Kosta Gaitanis
//      All rights reserved
//
//      k.gaitanis@gmail.com
//
// *********************************************************

#ifndef TESTMATRIX_H
#define TESTMATRIX_H

#include <QObject>
#include <QtTest/QtTest>

#include "Vector.h"
#include "Matrix.h"

class TestMatrix : public QObject
{
  Q_OBJECT
public:
    explicit TestMatrix(QObject *parent = 0) : QObject(parent) {}

private:

private slots:
    void testConvertToGL() {
        Matrix m(1, 2, 3, 4,
                 5, 6, 7, 8,
                 9, 10, 11, 12,
                 13, 14, 15, 16);

        GLdouble g[16] = {1, 5, 9, 13,
                         2, 6, 10, 14,
                         3, 7, 11, 15,
                         4, 8, 12, 16};

        Matrix fromGL = Matrix::fromGLArray(g);

        //qDebug() << m;
        //qDebug() << fromGL;

        QVERIFY(m == fromGL);

        GLdouble fromM[16];
        m.toGLArray(fromM);
        for (int i = 0; i < 16; i++) {
            QVERIFY(fromM[i] == g[i]);
        }

        m.toGLArray(g);
        Matrix mg = Matrix::fromGLArray(g);

        QVERIFY(m == mg);
    }

    /**
     * Test spatial transformation of a vector.
     */
    void testMatrixVectorTransformations()
    {
        double angle90 = 90.0 * M_PI / 180.0;

        Matrix pitch90 = Matrix::rotationX(angle90);
        Matrix roll90 = Matrix::rotationY(angle90);
        Matrix yaw90 = Matrix::rotationZ(angle90);
        Vector vTrans(1.0, 2.0, 3.0);

        Matrix mTrans = Matrix::translation(vTrans.x(), vTrans.y(), vTrans.z());

        // Y rotated 90 deg around X becomes Z
        QVERIFY(pitch90 * Vector::ORTHO_Y == Vector::ORTHO_Z);
        // X rotated 90 deg around Y becomes -Z
        QVERIFY(roll90 * Vector::ORTHO_X == -Vector::ORTHO_Z);
        // X rotated 90 deg around Z becomes Y
        QVERIFY(yaw90 * Vector::ORTHO_X == Vector::ORTHO_Y);

        // Test translation
        Vector v(12.0, 34.0, 56.0);
        QVERIFY(mTrans * v == vTrans + v);
    }

    /**
     * Test arbitrary axis rotations.
     */
    void testRotations()
    {
        double angle = -M_PI;
        while (angle < M_PI) {
            Matrix m1;
            Matrix m2;

            m1 = Matrix::rotationX(angle);
            m2 = Matrix::rotation(angle, Vector::ORTHO_X);

            QVERIFY(m1 == m2);

            m1 = Matrix::rotationX(-angle);
            m2 = Matrix::rotation(angle, -Vector::ORTHO_X);
            QVERIFY(m1 == m2);

            m1 = Matrix::rotationY(angle);
            m2 = Matrix::rotation(angle, Vector::ORTHO_Y);
            QVERIFY(m1 == m2);

            m1 = Matrix::rotationY(-angle);
            m2 = Matrix::rotation(angle, -Vector::ORTHO_Y);
            QVERIFY(m1 == m2);

            m1 = Matrix::rotationZ(angle);
            m2 = Matrix::rotation(angle, Vector::ORTHO_Z);
            QVERIFY(m1 == m2);

            m1 = Matrix::rotationZ(-angle);
            m2 = Matrix::rotation(angle, -Vector::ORTHO_Z);
            QVERIFY(m1 == m2);

            // Go to the next angle
            angle += M_PI / 100.0;
        }
    }
};

#endif // TESTMATRIX_H
